/*--------------------------------------------------------------------------
 *
 * 	You may freely copy, distribute, and reuse the code in this example.
 * 	SHL Systemhouse disclaims any warranty of any kind, expressed or  
 *	implied, as to its fitness for any particular use.
 *
 *
 *	IconWell
 *
 *	Inherits From:		View
 *
 *	Conforms To:		None
 *
 *	Declared In:		IconWell.h
 *
 *------------------------------------------------------------------------*/
#import "IconWell.h"
#import <appkit/appkit.h>




@implementation IconWell

/*--------------------------------------------------------------------------
 *	Private
 *------------------------------------------------------------------------*/
- (NXPoint) _centerPointForImage: anImage
{
	NXSize	imageSize;
	NXRect	boundsRect;
	
	[self getBounds: &boundsRect];
	[anImage getSize: &imageSize];
	
	if  (imageSize.width < NX_WIDTH (&boundsRect)) 
		NX_X (&boundsRect) += (NX_WIDTH (&boundsRect) 
			- imageSize.width ) / 2.0;
	
	if  (imageSize.height < NX_HEIGHT (&boundsRect)) 
		NX_Y (&boundsRect) += (NX_HEIGHT (&boundsRect) 
			- imageSize.height ) / 2.0;

	return boundsRect.origin;
}


- _dragOperationFor: (NXEvent*) originalEvent  nextEvent: (NXEvent*) nextEvent
{
 	id 		pasteboard;
	NXPoint	offset = { 0.0, 0.0 };
	NXRect	iconRect;
   	
	if (path == NULL)  return self;
	iconRect.origin = [self _centerPointForImage:icon];
 	pasteboard = [Pasteboard newName: NXDragPboard];
    [pasteboard declareTypes:&NXFilenamePboardType num:1 owner:self];
	[pasteboard writeType:NXFilenamePboardType data:path 
		length:strlen(path)+1];
    	
	[self dragImage:icon at:&iconRect.origin offset:&offset event:originalEvent 
		pasteboard:pasteboard source:self slideBack:YES];
		
	if (pasteboard) [pasteboard free];
//	[self notifyDelegateDidDrag];
	return self;
}


/*--------------------------------------------------------------------------
 *	Initialization and Freeing
 *------------------------------------------------------------------------*/
- initFrame:(const NXRect *)frameRect 
{
	[super initFrame: frameRect];
	[self registerForDraggedTypes: &NXFilenamePboardType count: 1];
  	return self;
}


- free
{
	if (icon) [icon free];
	if (path) NX_FREE (path);
  	return [super free];
}


/*--------------------------------------------------------------------------
 *	Accessors
 *------------------------------------------------------------------------*/
- icon 
{
  	return icon;
}


- setIcon:anIcon
{
	if (icon  &&  icon != anIcon)  [icon free];
	icon = anIcon;
	[self update];
	return self;
}
	

- (const char *)path 
{
  	return path;
}


- setPath:(const char *)aPath 
{
	if (path  &&  path != aPath)  NX_FREE (path);
	path = aPath ? NXCopyStringBuffer(aPath) : NULL;
	return self;
}
 

/*--------------------------------------------------------------------------
 *	Event Handling
 *------------------------------------------------------------------------*/
- (BOOL)acceptsFirstMouse
{
  	return YES;
}


- mouseDown: (NXEvent*) theEvent
{
	int		originalEventMask, newEventMask;
	NXEvent	originalEvent = *theEvent, nextEvent;

	if (path == NULL) return self;
	
    [NXApp preventWindowOrdering];
	originalEventMask = [window addToEventMask: NX_MOUSEDRAGGEDMASK];
	newEventMask = (NX_MOUSEUPMASK | NX_MOUSEDRAGGEDMASK);
	nextEvent = *([NXApp getNextEvent: newEventMask]);

	switch (nextEvent.type)
		{
		case NX_MOUSEDRAGGED:
//			if ([self notifyDelegateWillDrag] == YES)
			[self _dragOperationFor: &originalEvent  nextEvent: &nextEvent];
			break;
			
		case NX_MOUSEUP:
		default:
			break;
		}
	
	[window setEventMask: originalEventMask];
    	return self;
}


/*--------------------------------------------------------------------------
 *	Delegate
 *------------------------------------------------------------------------*/
- delegate
{
  	return delegate;
}


- setDelegate: anObject 
{
  	delegate = anObject;
  	return self;
}


/*--------------------------------------------------------------------------
 *	Drawing
 *------------------------------------------------------------------------*/
- drawSelf:(const NXRect *)rects :(int)rectCount 
{
	NXPoint	point = [self _centerPointForImage:icon];
	
 	PSsetgray(NX_LTGRAY);
  	PSrectfill(bounds.origin.x, bounds.origin.y, bounds.size.width, 
		bounds.size.height);

  	[icon composite:NX_SOVER toPoint:&point];
	return self;
}


/*--------------------------------------------------------------------------
 *	Dragging
 *------------------------------------------------------------------------*/
- (NXDragOperation) draggingSourceOperationMaskForLocal: (BOOL)isLocal;
{	
	return NX_DragOperationCopy;
}


- (NXDragOperation) draggingEntered:dragSource
{
    return NX_DragOperationCopy;
}


- (NXDragOperation) draggingUpdated:dragSource
{
	if ([dragSource draggingSource] == self) 
		return NX_DragOperationNone; 

    return NX_DragOperationCopy;
}


- (BOOL) prepareForDragOperation:dragSource
{
//	return [self notifyDelegateWillDrag];
	return YES;
}


- (BOOL) performDragOperation:dragSource
{
	id		pasteboard;
	char*	data;
	int 	length;

	pasteboard = [dragSource draggingPasteboard];
	[pasteboard readType:NXFilenamePboardType data:&data length:&length];
	if (strchr (data, '\t')) return NO;
	[self setPath: data];
	[self setIcon: [dragSource draggedImageCopy]];
	[pasteboard deallocatePasteboardData:data length:length];
	return YES;
}


- notifyDelegateDidDrop: aDragSource
{
	if ([delegate respondsTo: @selector (dragSource:didDropOnIconWell:)])
		[delegate dragSource: aDragSource didDropOnIconWell: self];

	return self;
}


- concludeDragOperation:dragSource
{
	[self notifyDelegateDidDrop: dragSource];
	[self update];
	return self;
}


@end
